<template>
  <el-form
    :ref="formRef"
    v-bind="{ ...$attrs, ...otherAttrs }"
    :model="normalizedFormData"
  >
    <template v-for="item in renderFormItem">
      <div
        :is="item.col ? 'el-col' : 'div'"
        v-if="!item.isHide"
        :key="item.key"
        :span="item.col"
      >
        <div v-if="item.type === 'title'" v-bind="item.otherAttrs">
          {{ item.label }}
        </div>
        <form-item
          v-else
          :type="item.type"
          :label="item.label"
          :prop="item.key"
          :form-data="normalizedFormData"
          :slot-attrs="item.slotAttrs"
          :rules="formatRules(item)"
          v-bind="item.otherAttrs"
          height="32px"
          v-on="item.slotListeners"
        />
      </div>
      <!-- <form-item
        v-else-if="!item.isHide"
        :key="item.key"
        :type="item.type"
        :label="item.label"
        :prop="item.key"
        :form-data="normalizedFormData"
        :slot-attrs="item.slotAttrs"
        :rules="formatRules(item)"
        v-bind="{...item.otherAttrs}"
        v-on="item.slotListeners"
      /> -->
    </template>
    <template v-if="!isHideButtons">
      <el-col v-if="formButtons.isDialog" :span="24">
        <div class="empty-block" />
        <div class="dialog-action-box">
          <el-button
            v-if="formButtons.otherBtn"
            type="formButtons.otherBtn.type || 'default"
            size="small"
            @click="
              () => {
                formButtons.otherBtn.click(formRef)
              }
            "
          >
            {{ formButtons.otherBtn.name }}
          </el-button>
          <el-button
            type="primary"
            size="small"
            :disabled="formButtons.submitDisabled || false"
            @click="submitForm(formRef)"
          >
            {{ formButtons.submitName || '提交' }}
          </el-button>
          <el-button size="small" @click="resetForm(formRef)">
            {{ formButtons.resetName || '取消' }}
          </el-button>
        </div>
      </el-col>
      <div
        :is="formButtons.col ? 'el-col' : 'div'"
        v-else
        :span="formButtons.col"
      >
        <el-form-item>
          <el-button type="primary" @click="submitForm(formRef)">
            {{ formButtons.submitName || '查询' }}
          </el-button>
          <el-button @click="resetForm(formRef)">
            {{ formButtons.resetName || '重置' }}
          </el-button>
        </el-form-item>
      </div>
      <!-- <el-form-item v-else>
        <el-button
          type="primary"
          @click="submitForm(formRef)"
        >
          {{ formButtons.submitName || '查询' }}
        </el-button>
        <el-button @click="resetForm(formRef)">
          {{ formButtons.resetName || '重置' }}
        </el-button>
      </el-form-item> -->
    </template>
    <div class="clear" />
  </el-form>
</template>

<script>
import FormItem from './FormItem'

export default {
  name: 'SuperForm',
  components: { FormItem },
  props: {
    formRef: {
      // form 的 ref
      type: String,
      default: ''
    },
    formData: {
      // form 的 数据
      type: Object,
      default: () => ({})
    },
    otherAttrs: {
      // form 的其他属性
      type: Object,
      default: () => ({})
    },
    renderFormItem: {
      // formItem 的参数
      type: Array,
      default: () => []
    },
    formButtons: {
      // form 按钮
      type: Object,
      default: () => ({})
    },
    isHideButtons: {
      // 是否隐藏按钮
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      normalizedFormData: {}
    }
  },
  watch: {
    formData: {
      handler: function(val) {
        let data = { ...this.normalizedFormData, ...val }
        if (JSON.stringify(this.formData) === JSON.stringify({})) {
          data = {}
        }
        this.$data.normalizedFormData = this.formatInitFormData(data)
      },
      deep: true,
      immediate: true
    }
  },
  methods: {
    setFormData(data) {
      // 外部调用设置值
      this.normalizedFormData = {
        ...this.normalizedFormData,
        ...data
      }
    },
    getFormData() {
      return this.normalizedFormData
    },
    formatRules(_formItem) {
      if (_formItem.rules) {
        return _formItem.rules
      }
      if (_formItem.required) {
        return {
          required: true,
          message: _formItem.label + '不能为空',
          trigger: 'blur'
        }
      }
      return null
    },
    formatFormData(_submitData) {
      const result = {}
      Object.keys(_submitData).forEach(e => {
        const currentRender = this.$props.renderFormItem.find(
          ee => ee.key === e
        )
        if (currentRender && currentRender.subKey) {
          currentRender.subKey.forEach((eee, iii) => {
            const currentSub = _submitData[e] || []
            result[eee] = currentSub[iii]
          })
        } else {
          result[e] = _submitData[e]
        }
      })
      return result
    },

    formatInitFormData(_initData = {}) {
      const result = {}
      this.$props.renderFormItem.forEach(e => {
        if (e.subKey) {
          result[e.key] = []
          e.subKey.forEach(ee => {
            _initData[ee] && result[e.key].push(_initData[ee])
          })
          result[e.key].length === 0 && (result[e.key] = null)
        } else {
          result[e.key] = _initData[e.key]
        }
      })
      return { ..._initData, ...result }
    },

    submitForm(formName) {
      this.$refs[formName].validate(valid => {
        if (valid) {
          const formData = this.formatFormData(this.$data.normalizedFormData)
          this.formButtons.submitCallback &&
            this.formButtons.submitCallback(formData)
        }
      })
    },
    resetForm(formName) {
      this.$refs[formName].resetFields()
      const formData = this.formatFormData(this.$data.normalizedFormData)
      this.formButtons.resetCallback && this.formButtons.resetCallback(formData)
    }
  }
}
</script>

<style lang="scss" scoped>
/deep/ label {
  font-weight: 400;
}
/deep/ .el-form-item {
  margin-bottom: 18px;
}
.clear {
  clear: both;
}
.empty-block {
  height: 32px;
}
.dialog-action-box {
  width: 100%;
  border-top: 1px solid #eaeaea;
  position: absolute;
  left: 0;
  bottom: 0;
  height: 58px;
  text-align: center;
  padding-top: 12px;
}
</style>
